/*
 * 文件功能说明：
 * 该文件实现了通过HC-SR04超声波测距模块测量距离的功能。
 * HC-SR04模块通过GPIO7和GPIO8连接到3861。
 * - GPIO7用于触发超声波模块发出脉冲信号。
 * - GPIO8用于接收超声波模块返回的回响信号。
 * 本模块通过测量回响信号的高电平持续时间，计算出物体与传感器之间的距离。
 */

 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>
 
 #include "ohos_init.h"
 #include "cmsis_os2.h"
 #include "iot_gpio.h"
 #include "hi_io.h"
 #include "hi_time.h"
 
 // HC-SR04 超声波测距模块通过GPIO7和8连接到3861
 #define GPIO_8 8          // GPIO 8用于接收超声波回响信号
 #define GPIO_7 7          // GPIO 7用于触发超声波脉冲信号

 #define DISTANCE_STOP 20
 #define GPIO_FUNC 0       // 设置GPIO的功能模式
 uint8_t  SR04_flag = 0;   // 超声波障碍物标志位定义
 /*
  * 函数：GetDistance
  * 功能：使用HC-SR04超声波模块测量物体与传感器之间的距离。
  *      该函数通过输出脉冲信号并测量回响信号的时间，利用公式计算出距离。
  * 输入：无
  * 输出：返回测得的距离值（单位：厘米）
  */
 float GetDistance(void)
 {
     static unsigned long start_time = 0, time = 0; // 记录开始时间和回响信号的持续时间
     float distance = 0.0; // 距离（单位：厘米）
     IotGpioValue value = IOT_GPIO_VALUE0; // 存储GPIO的输入值
     unsigned int flag = 0; // 标记，用于区分回响信号的开始和结束
 
     IoTWatchDogDisable(); // 禁用看门狗定时器，以防止超时重启
     hi_io_set_func(GPIO_8, GPIO_FUNC); // 设置GPIO8为输入模式
 
     IoTGpioSetDir(GPIO_8, IOT_GPIO_DIR_IN); // 设置GPIO_8为输入模式
     IoTGpioSetDir(GPIO_7, IOT_GPIO_DIR_OUT); // 设置GPIO_7为输出模式
 
     // 触发超声波模块发出脉冲信号
     IoTGpioSetOutputVal(GPIO_7, IOT_GPIO_VALUE1); // 输出高电平
     hi_udelay(20); // 延时20微秒
     IoTGpioSetOutputVal(GPIO_7, IOT_GPIO_VALUE0); // 输出低电平
 
     // 等待并测量回响信号的高电平时间（添加超时机制）
     unsigned int timeout_start = hi_get_us();
     unsigned int timeout_limit = 30000; // 30ms超时限制

     while (1) {
         // 检查超时
         if (hi_get_us() - timeout_start > timeout_limit) {
             // 超时，设置默认安全距离
             distance = 100.0; // 假设100cm，表示没有障碍物
             SR04_flag = 0;
             printf("SR04 timeout - assuming clear\r\n");
             return distance;
         }

         IoTGpioGetInputVal(GPIO_8, &value); // 获取GPIO_8的输入值

         // 当回响信号为高电平时，记录开始时间
         if (value == IOT_GPIO_VALUE1 && flag == 0)
         {
             start_time = hi_get_us(); // 获取当前时间（微秒）
             flag = 1; // 标记开始
         }

         // 当回响信号为低电平时，计算时间差并结束测量
         if (value == IOT_GPIO_VALUE0 && flag == 1)
         {
             time = hi_get_us() - start_time; // 计算回响信号的持续时间
             start_time = 0; // 重置开始时间
             break; // 退出循环
         }
     }
 
     // 使用公式计算距离：距离 = 时间 * 声速 / 2
     // 声速是0.034厘米/微秒，除以2是因为声波需要来回传播
     distance = time * 0.034 / 2;
     if(distance < DISTANCE_STOP)
     {
        SR04_flag = 1;
     }
     else
     {
        SR04_flag = 0;
     }
     
    printf("distance is %f\r\n", distance); // 输出计算得到的距离
    printf("SR04_flag : %d \r\n",SR04_flag);
    //print_trace_info();
    
     return distance; // 返回距离值
 }
 
 void GetDistance_Task(void *arg)
{      
    (void) arg;
    printf("I am GetDistance_Task\r\n");

    while (1) 
    {
        float a = GetDistance();
        printf("distance is %.2f\r\n", a);
        printf("SR04_flag : %d \r\n", SR04_flag);

        osDelay(100); // 延时100ms，避免线程跑满CPU
    }
}

void HCSR04_Thread(void)
{
    osThreadAttr_t attr;

    attr.name = "HCSR04_Thread";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 4056;
    attr.priority = 23;
    printf("I am HCSR04_Thread\r\n");
    if (osThreadNew((osThreadFunc_t)GetDistance_Task, NULL, &attr) == NULL) 
    {
        printf("[HCSR04_Thread] Falied to create Ssd1306TestTask!\n");
    }
}
APP_FEATURE_INIT(HCSR04_Thread);